import rulesConfig from './config';
import { StateType } from '@/common-typings';

class Validator {
  public rules = {};

  constructor() {
    Object.keys(rulesConfig).forEach(name => {
      this.setRules(rulesConfig[name], name);
      this.createValidate(rulesConfig[name], name, rulesConfig[name].flag);
    });
    return this;
  }

  /**
   * 设置校验
   */
  setRules(item: StateType, name: string) {
    if (!this.rules[name]) {
      this.rules[name] = {
        reg: item.reg,
        desc: item.desc,
      };
    }
    return this;
  }

  /**
   * 判断校验项是否存在
   */
  isExistRules(name: string) {
    if (!this.rules[name]) {
      return false;
    }
    return true;
  }

  /**
   * 获取字符串字节长度
   */
  getStrLen = (str: string) => {
    let realLength = 0;
    let charCode;
    for (let i = 0; i < str.length; i += 1) {
      charCode = str.charCodeAt(i);
      if (charCode >= 0 && charCode <= 128) realLength += 1;
      else realLength += 2;
    }
    return realLength;
  };

  /**
   * 校验判断
   */
  test(name: string, value: any, flag: boolean, rule: StateType) {
    const self = this;
    let res = {};
    if (self.isExistRules(name)) {
      const rules = self.rules[name];
      let regex = rules.reg;
      let tips = rules.desc;
      let check;
      let val;
      switch (name) {
        // 必填项
        case 'required':
          if (value === '' || value === null || value === undefined) {
            check = false;
            tips = rule.msg ? rule.msg + tips : tips;
          } else {
            check = true;
          }
          break;
        case 'maxLength':
          if (value) {
            val = value.toString();
            regex = rule.maxLength ? rule.maxLength : rules.reg;
            tips = `最多支持${regex}位字符(中文不可超过${regex / 2}位)`;
            check = !(this.getStrLen(val) > regex);
          } else {
            check = true;
          }
          break;
        case 'alipayMaxLength':
          val = value.toString();
          check = !(this.getStrLen(val) > regex);
          break;
        default:
          if (regex.global) regex.lastIndex = 0;
          check = regex.test(value);
          break;
      }
      res = {
        check: flag ? !check : check,
        desc: new Error(tips),
      };
    } else {
      res = {
        check: false,
        desc: new Error('检验项为空'),
      };
    }
    return res;
  }

  /**
   * 创建校验规则
   */
  createValidate(ruleConfig: StateType, name: string, flag = false) {
    const self = this;
    if (!self[name]) {
      self[name] = (rule: StateType, value: any, cb: Function) => {
        if (rule.flag) {
          ({ flag } = rule);
        }
        const r: StateType = self.test(name, value, flag, rule);
        if (r.check) {
          cb();
        } else {
          cb(r.desc);
        }
      };
    }
  }

  static instance: any;

  static getInstance() {
    if (!this.instance) {
      this.instance = new Validator();
    }
    return this.instance;
  }
}

export default Validator.getInstance();
